package com.pattern.serviceLocator;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Mr.yuan
 * @version v1.0
 * @date 2019/7/25 13:39
 **/
public class ServiceLocatorPattern {
    /**
     *
     * 服务定位器模式（Service Locator Pattern）用在我们想使用 JNDI 查询定位各种服务的时候。
     * 考虑到为某个服务查找 JNDI 的代价很高，服务定位器模式充分利用了缓存技术。
     * 在首次请求某个服务时，服务定位器在 JNDI 中查找服务，并缓存该服务对象。
     * 当再次请求相同的服务时，服务定位器会在它的缓存中查找，这样可以在很大程度上提高应用程序的性能。
     * 以下是这种设计模式的 实体。
     *  -服务（Service） - 实际处理请求的服务。对这种服务的引用可以在 JNDI 服务器中查找到。
     *  -Context / 初始的 Context - JNDI Context 带有对要查找的服务的引用。
     *  -服务定位器（Service Locator） - 服务定位器是通过 JNDI 查找和缓存服务来获取服务的单点接触。
     *  -缓存（Cache） - 缓存存储服务的引用，以便复用它们。
     *  -客户端（Client） - Client 是通过 ServiceLocator 调用服务的对象。
     **/

    public static void main(String[] args) {
        Service service1 = new ServiceLocator().getService("service1");
        service1.execute();
        Service service2 = new ServiceLocator().getService("service2");
        service2.execute();
        service1 = new ServiceLocator().getService("service1");
        service1.execute();
        service2 = new ServiceLocator().getService("service2");
        service2.execute();
    }

    interface Service{
        String getName();
        void execute();
    }

    static class Service1 implements Service {
        @Override
        public String getName() {
            return "service1";
        }

        @Override
        public void execute() {
            System.out.println("execute service1");
        }
    }
    static class Service2 implements Service {
        @Override
        public String getName() {
            return "service2";
        }

        @Override
        public void execute() {
            System.out.println("execute service2");
        }
    }

    static class InitContext {
        private Service lookup(String name) {
            if (name.equalsIgnoreCase("service1")) {
                System.out.println("lookup and create a service1");
                return new Service1();
            }
            if (name.equalsIgnoreCase("service2")) {
                System.out.println("lookup and create a service2");
                return new Service2();
            }
            return null;
        }
    }

    static class Cache {
        private List<Service> list;
        Cache() {
            list = new ArrayList<>();
        }

        private Service getService(String name) {
            for (Service service : list) {
                if (service.getName().equalsIgnoreCase(name)){
                    System.out.println("return cache "+name);
                    return service;
                }
            }
            return null;
        }
        private void addService(Service newService) {
            boolean exist = false;
            for (Service service : list) {
                if (service.getName().equalsIgnoreCase(newService.getName())) {
                    exist = true;
                }
            }
            if (!exist) {
                list.add(newService);
            }

        }
    }
    static class ServiceLocator {
        private static Cache cache;
        static {
            cache = new Cache();
        }
        private Service getService(String name){
            Service service = cache.getService(name);
            if (null != service){
                return service;
            }
            InitContext context = new InitContext();
            service = context.lookup(name);
            cache.addService(service);
            return service;
        }
    }
}
